<template>
	<div class="page">
		<div class="p-10 system-page-background b-radius-4">
			<my-form inline query label-width="70px" :model="queryParams" :form-item="queryFormItem" :search-fn="() => refTable.reload()" />
		</div>
		<div class="flex-auto flex-col m-t-10 system-page-background b-radius-4">
			<div v-hasPermi="['system:role:add', 'system:role:remove', 'system:role:export']" class="p-10">
				<el-button v-hasPermi="['system:role:add']" type="primary" icon="Plus" @click.prevent="Add">新增</el-button>
				<el-button-group>
					<my-button-export v-hasPermi="['system:role:export']" :load="Export" :disabled="!state.list.length" />
				</el-button-group>
				<el-button
					v-hasPermi="['system:role:remove']"
					type="danger"
					:disabled="!tableSelection.length"
					icon="Delete"
					@click.prevent="deleteFn(tableSelection)"
				>
					删除
				</el-button>
			</div>
			<my-list-panel ref="refTable" :load-fn="loadData" :total="state.total">
				<my-table :data="state.list" :columns="state.columns" @selection-change="(val) => (tableSelection = val)">
					<template #status="{ row }">
						<el-switch
							v-model="row.status"
							inline-prompt
							:active-value="0"
							:inactive-value="1"
							active-text="启"
							inactive-text="停"
							@change="StatusChange(row)"
						></el-switch>
					</template>
					<template #default="{ row }">
						<my-button-text v-hasPermi="['system:role:edit']" @click.prevent="Update(row)">修改</my-button-text>
						<my-button-text v-hasPermi="['system:role:data']" @click.prevent="DataScope(row)">数据权限</my-button-text>
					</template>
				</my-table>
			</my-list-panel>
		</div>

		<!-- 添加或修改角色配置对话框 -->
		<el-dialog v-model="dialog.open" :title="dialog.title" width="600px" append-to-body @closed="resetForm(form)">
			<el-form ref="refDialogForm" :model="dialog.form" :rules="rules" label-width="80px" class="validate--bottom dialog-form">
				<el-form-item label="角色名称" prop="roleName">
					<my-input v-model="dialog.form.roleName" placeholder="请输入角色名称" />
				</el-form-item>
				<el-form-item label="权限字符" prop="roleKey">
					<my-input v-model="dialog.form.roleKey" placeholder="请输入权限字符" />
				</el-form-item>
				<el-form-item label="角色顺序" prop="roleSort">
					<my-input-number v-model="dialog.form.roleSort" :min="0" :maxlength="10" number-type="init" />
				</el-form-item>
				<el-form-item label="状态" prop="status">
					<el-radio-group v-model="dialog.form.status">
						<el-radio v-for="dict in $store.dict.sysNormalDisable" :key="dict.dictValue" :value="dict.dictValue * 1">{{ dict.dictLabel }}</el-radio>
					</el-radio-group>
				</el-form-item>
				<el-form-item label="菜单数据">
					<el-checkbox v-model="dialog.menuExpand" @change="CheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
					<el-checkbox v-model="dialog.menuNodeAll" @change="CheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
					<el-checkbox v-model="dialog.form.menuStrictly" :true-label="1" :false-label="0">父子联动</el-checkbox>
					<el-tree
						ref="refMenu"
						accordion
						:check-strictly="!dialog.form.menuStrictly"
						class="tree-border overflow-y-auto"
						:data="menuOptions"
						show-checkbox
						node-key="id"
						empty-text="加载中，请稍后"
						:props="{ children: 'children', label: 'menuName' }"
						style="min-height: 100px; max-height: 250px"
					/>
				</el-form-item>
				<el-form-item label="备注">
					<my-input v-model="dialog.form.remark" type="textarea" placeholder="请输入内容" />
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="cancel">取消</el-button>
				<el-button type="primary" @click="submitForm()">确定</el-button>
			</template>
		</el-dialog>

		<!-- 分配角色数据权限对话框 -->
		<el-dialog v-model="dialog.openDataScope" :title="dialog.title" width="600px" append-to-body>
			<el-form :model="dialog.form" label-width="100px" class="validate--bottom dialog-form">
				<el-form-item label="角色名称">
					<my-input v-model="dialog.form.roleName" disabled />
				</el-form-item>
				<el-form-item label="权限字符">
					<my-input v-model="dialog.form.roleKey" disabled />
				</el-form-item>
				<el-form-item label="权限范围">
					<el-select v-model="dialog.form.dataScope">
						<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
					</el-select>
				</el-form-item>
				<el-form-item v-show="dialog.form.dataScope == 2" label="数据权限">
					<el-checkbox v-model="dialog.deptExpand" @change="CheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
					<el-checkbox v-model="dialog.deptNodeAll" @change="CheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
					<el-checkbox v-model="dialog.form.deptStrictly" :true-label="1" :false-label="0">父子联动</el-checkbox>
					<el-tree
						ref="refDept"
						accordion
						:check-strictly="!dialog.form.deptStrictly"
						class="tree-border overflow-y-auto"
						:data="deptOptions"
						show-checkbox
						default-expand-all
						node-key="id"
						empty-text="加载中，请稍后"
						:props="{ children: 'children', label: 'deptName' }"
						style="min-height: 100px; max-height: 150px"
					/>
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="cancelDataScope">取消</el-button>
				<el-button type="primary" @click="submitDataScope()">确定</el-button>
			</template>
		</el-dialog>
	</div>
</template>

<script setup name="system/role">
import { pageRole, removeRole, addRole, editRole, infoRole, exportRole } from '@/api/system';
import { changeRoleStatus, changeDataPerm, getRoleMenuList, getRoleDeptList } from '@/api/public';
import { downloadBlob } from '@u/download';

const dataScopeOptions = [
		{
			value: 1,
			label: '全部数据权限'
		},
		{
			value: 2,
			label: '自定数据权限'
		},
		{
			value: 3,
			label: '本部门数据权限'
		},
		{
			value: 4,
			label: '本部门及以下数据权限'
		},
		{
			value: 5,
			label: '仅本人数据权限'
		}
	],
	rules = {
		roleName: [{ required: true, message: '角色名称不能为空', trigger: 'change' }],
		roleKey: [{ required: true, message: '权限字符不能为空', trigger: 'change' }],
		roleSort: [{ required: true, message: '角色顺序不能为空', trigger: 'change' }]
	};

/**************************表格逻辑***************************** */
const queryFormItem = [
		{ prop: 'likeRoleName', label: '角色名称' },
		{ prop: 'likeRoleKey', label: '权限字符' },
		{
			itemType: 'select',
			prop: 'status',
			label: '状态',
			list: $store.dict.sysNormalDisable
		},
		{
			itemType: 'date',
			prop: 'dateRange',
			label: '创建时间',
			type: 'datetimerange',
			rangeSeparator: '至',
			startPlaceholder: '开始日期',
			endPlaceholder: '结束日期',
			prepend: 'CreateTime'
		}
	],
	columns = [
		{
			type: 'selection'
		},
		{
			label: '角色编号',
			prop: 'id'
		},
		{
			label: '角色名称',
			prop: 'roleName'
		},
		{
			label: '权限字符',
			prop: 'roleKey'
		},
		{
			label: '显示顺序',
			prop: 'roleSort'
		},
		{
			label: '状态',
			prop: 'status'
		},
		{
			label: '创建时间',
			prop: 'createTime',
			width: 160
		},
		{
			label: '操作',
			width: 150
		}
	];

const { queryParams, refTable, state, tableSelection, getList, loadData, deleteFn, dialog, refDialogForm } = pageMixin({
	queryFormItem,
	queryParamsDefault: {
		orderByColumn: 'roleSort',
		isAsc: 'asc'
	},
	columns,
	api: { page: pageRole, remove: removeRole },
	dialogDefault: {
		title: '',
		// 角色弹窗
		open: false,
		form: {
			id: undefined,
			roleName: '',
			roleKey: '',
			roleSort: 0,
			status: 0,
			menuIds: [],
			deptIds: [],
			menuStrictly: 1,
			deptStrictly: 1,
			remark: ''
		},
		// 是否显示弹出层（数据权限）
		openDataScope: false,
		menuExpand: false,
		menuNodeAll: false,
		deptExpand: true,
		deptNodeAll: false
	}
});

// 取消按钮
function cancel() {
	dialog.open = false;
	dialog.menuExpand = false;
	dialog.menuNodeAll = false;
	dialog.deptExpand = true;
	dialog.deptNodeAll = false;
}
/** 新增按钮操作 */
function Add() {
	resetForm(refDialogForm);
	getMenuTreeselect();
	dialog.open = true;
	dialog.title = '添加角色';
	dialog.form.id = undefined;
	nextTick(() => {
		refMenu.value.setCheckedKeys([]);
	});
}
/** 修改按钮操作 */
function Update(row) {
	const roleId = row.id;
	const roleTreeInfo = getRoleMenuTreeselect(roleId);
	Promise.all([
		infoRole({ id: row.id }).then((res) => {
			dialog.open = true;
			dialog.title = '修改角色';
			nextTick(() => {
				dialog.form = res.data;
			});
		}),
		nextTick(() => {
			roleTreeInfo.then((res) => {
				refMenu.value.setCheckedKeys(res.data.ruleMenuIds);
			});
		})
	]);
}
/** 分配数据权限操作 */
function DataScope(row) {
	infoRole({ id: row.id }).then((res) => {
		dialog.openDataScope = true;
		dialog.title = '分配数据权限';
		nextTick(() => {
			dialog.form = res.data;
		});
	});
	getRoleDeptTreeselect(row.id).then((res) => {
		refDept.value.setCheckedKeys(res.data.ruleDeptIds);
	});
}
/** 提交按钮 */
function submitForm() {
	refDialogForm.value.validate((valid) => {
		if (valid) {
			dialog.form.menuIds = getMenuAllCheckedKeys();
			if (dialog.form.id != undefined) {
				editRole(dialog.form).then(() => {
					msgSuccess('修改成功');
					cancel();
					getList();
				});
			} else {
				addRole(dialog.form).then(() => {
					msgSuccess('新增成功');
					cancel();
					getList();
				});
			}
		}
	});
}
/**
 * 启用、停用
 * @param {Object} row 行数据
 */
function StatusChange(row) {
	if (row.id) {
		const text = row.status === 0 ? '启用' : '停用';
		confirmFn({ item: `确认要—${text}（${row.roleName}）角色吗?` })
			.then(() => changeRoleStatus({ id: row.id, status: row.status }))
			.then(() => {
				msgSuccess(text + '成功');
			})
			.catch(function () {
				row.status = row.status === 0 ? 1 : 0;
				msgInfo('已取消！');
			});
	}
}
/** 导出按钮操作 */
function Export() {
	return exportRole(queryParams).then((data) => {
		downloadBlob(data, '角色管理.xlsx');
	});
}
$store.dict.GETsysNormalDisable();

/**************************************权限逻辑************************************** */
const menuOptions = ref([]),
	deptOptions = ref([]);
const refMenu = shallowRef(null),
	refDept = shallowRef(null);
/** 查询菜单树结构 */
function getMenuTreeselect() {
	getRoleMenuList().then((res) => {
		menuOptions.value = res.data.menus;
	});
}
/** 根据角色ID查询菜单树结构 */
function getRoleMenuTreeselect(roleId) {
	return getRoleMenuList({ roleId: roleId }).then((res) => {
		menuOptions.value = res.data.menus;
		return res;
	});
}

// 所有菜单节点数据
function getMenuAllCheckedKeys() {
	// 目前被选中的菜单节点
	const checkedKeys = refMenu.value.getCheckedKeys();
	// 半选中的菜单节点
	const halfCheckedKeys = refMenu.value.getHalfCheckedKeys();
	checkedKeys.unshift(...halfCheckedKeys);
	return checkedKeys;
}
// 所有部门节点数据
function getDeptAllCheckedKeys() {
	// 目前被选中的部门节点
	const checkedKeys = refDept.value.getCheckedKeys();
	// 半选中的部门节点
	const halfCheckedKeys = refDept.value.getHalfCheckedKeys();
	checkedKeys.unshift(...halfCheckedKeys);
	return checkedKeys;
}

// 取消按钮（数据权限）
function cancelDataScope() {
	dialog.openDataScope = false;
	dialog.menuExpand = false;
	dialog.menuNodeAll = false;
	dialog.deptExpand = true;
	dialog.deptNodeAll = false;
}
// 树权限（展开/折叠）
function CheckedTreeExpand(value, type) {
	if (type == 'menu') {
		const treeList = menuOptions.value;
		for (let i = 0; i < treeList.length; i++) {
			refMenu.value.store.nodesMap[treeList[i].id].expanded = value;
		}
	} else if (type == 'dept') {
		const treeList = deptOptions.value;
		for (let i = 0; i < treeList.length; i++) {
			refDept.value.store.nodesMap[treeList[i].id].expanded = value;
		}
	}
}
// 树权限（全选/全不选）
function CheckedTreeNodeAll(value, type) {
	if (type == 'menu') {
		nextTick(() => {
			refMenu.value.setCheckedNodes(value ? menuOptions.value : []);
		});
	} else if (type == 'dept') {
		nextTick(() => {
			refDept.value.setCheckedNodes(value ? deptOptions.value : []);
		});
	}
}
/** 根据角色ID查询部门结构 */
function getRoleDeptTreeselect(roleId) {
	return getRoleDeptList({ roleId: roleId }).then((res) => {
		deptOptions.value = res.data.depts;
		return res;
	});
}

/** 提交按钮（数据权限） */
function submitDataScope() {
	if (dialog.form.id != undefined) {
		dialog.form.deptIds = getDeptAllCheckedKeys();
		changeDataPerm(dialog.form).then(() => {
			msgSuccess('修改成功');
			cancelDataScope();
			getList();
		});
	}
}
</script>

<style lang="scss" scoped>
.tree-border {
	margin-top: 5px;
	border: 1px solid #e5e6e7;
	border-radius: 4px;
}

.dialog-form :deep(.el-form-item__content) {
	display: block;
}
</style>
